/*
 *  GL_routines.cpp
 *  Pirates2011
 *
 *  Created by Alan Dorin on 25/03/11.
 *  Copyright 2011 __MyCompanyName__. All rights reserved.
 *
 */


using namespace std;

#include "GL_routines.h"
#include "Sea.h"
#include <iostream>
#include <fstream>

extern void cleanQuit(char *);
extern Sea* gSea;
extern Globals gGlobal;

bool pausedFlag = true;		// simulation paused
bool stepFlag = false;		// step mode
bool displayUpdateFlag = true;

void myLight(void)
{
	// no lighting
}

void initGL(long windowID)
{
   glClearColor (0.00, 0.0, 0.15, 0.0);
   glShadeModel (GL_SMOOTH);				// alternative: GL_FLAT
   
   glEnable(GL_POINT_SMOOTH);
   glutSetCursor(GLUT_CURSOR_LEFT_ARROW);
   
   glPointSize(3.0);
}

void display(void)
{
	if (!displayUpdateFlag) return;
	
	glutSetCursor(GLUT_CURSOR_LEFT_ARROW);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glColor3f(1.0, 1.0, 1.0);							// default white colour
	glLoadIdentity ();						      		// clear the matrix

	glDepthMask(GL_FALSE);
	
    // just display here (update in the animate() function)
	gSea->display();
	glDepthMask(GL_TRUE);	   
	glFlush ();
	glutSwapBuffers();
}

void reshape (int w, int h)
{
	GLsizei viewportWidth, viewportHeight;
	GLsizei widthRemainder, heightRemainder;
	
	// calculate maximum dimension (width or height) to give the maximum square dimension
	viewportWidth = viewportHeight = ((w>h) ? h : w);
	
	// calc. the remainder of the screen after the square dimension
	// in the other (greater) of width or height
	widthRemainder = (w - viewportWidth) / 2;
	heightRemainder = (h - viewportHeight) / 2;
	
	glViewport(widthRemainder, heightRemainder, viewportWidth, viewportHeight);
	glMatrixMode (GL_PROJECTION);
	glLoadIdentity ();
	
	// Set up the orthographic view
	glOrtho(-0.05, 1.0, -0.05, 1.0, -1, +1);
	
	glMatrixMode (GL_MODELVIEW);
}

/* ARGSUSED1 */
void keyboard(unsigned char key, int x, int y)
{
	ofstream outFile;
	ifstream inFile;

	switch (key) {
        case 'c':
        	glutPostRedisplay();
      	break;
		
		case 'd':
			displayUpdateFlag = !displayUpdateFlag;
		break;
		
		case 'p':
			pausedFlag = !pausedFlag;
		break;
		
		case 'o':	// one step
			// always turn on pause if step mode is turned on, this way we update the frame count during stepping
			// just once, then return to being paused...
			pausedFlag = true;
			stepFlag = true;
			// update() and redisplay() will be called naturally via animate() during system Idle. This will execute just once
			// since pausedFlag is true
			glutPostRedisplay();
		break;
		
		case 's':
			/* disabled game save
			cout << "\nSaving file patch.dat";
			outFile.open("patch.dat", ios::out);
			gSea->fileOutput(outFile);
			outFile.close();
			*/
		break;
		
		case 'l':
			/* disabled game load
			cerr << "\nLoading file patch.dat";
			inFile.open("patch.dat", ios::in);
			if (inFile.fail())
			{	std::cerr << "\nError could not open input file: patch.dat. Continuing without doing load...";	}
			
			if (gSea)
			{
				delete gSea;			// free up the old patch
			}
			
			gSea = new Sea();
			gSea->fileInput(inFile);
			inFile.close();
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
			glutPostRedisplay();
			*/
		break;
        
		case 27:	// ESC key
      	case 'q':
      	case 'Q':
      		cleanQuit("\nThankyou for playing!");
      	break;
              	
      	default:
      	break;
   }
}

void mouse(int button, int state, int x, int y)
{
	return;
}

void mouseMove(int x, int y)
{
	return;
}

void mousePassiveMove(int x, int y)
{
    return;
}


void visible(int vis)
{
	if (vis == GLUT_VISIBLE)	glutIdleFunc(animate);
	else						glutIdleFunc(NULL);
}

void animate(void)
{
	extern void restart(void);
	static long curFrame=0;
	static long curSimulationRepeat=0;
	long frameInterval = 1000;
	bool mute = true, gameAliveFlag = true;
	
	if ((pausedFlag == false) || (stepFlag==true))
	{
		gameAliveFlag = gSea->update();		// update returns false if all ships have been sunk
		glutPostRedisplay();
	
		if (! (curFrame % frameInterval) || (gameAliveFlag == false))
		{	mute = false;	}
		
		gSea->computeAndOutputShipStatistics(curFrame, mute);
		curFrame++;
		
		// if we got in here b/c stepFlag was true, we have now done our one step
		// so now pause the simulation again waiting for either an unpause or another step.
		stepFlag = false;
	}
	
	if ((curFrame > gGlobal.numSimulationTimeSteps) || (gameAliveFlag == false))
	{
		// output game's final result
		gSea->computeAndOutputShipStatisticsGameOver(curFrame);
		
		// restart!
		restart();
		curFrame = 0;
		curSimulationRepeat++;
	}
	
	if (curSimulationRepeat >= gGlobal.numSimulationRepeatRuns)
	{
		cleanQuit("Finished all runs!");
	}
}

void null_select(int mode)
{	/* nothing */ }

void menu_select(int mode)
{
	char c='s';
	
	switch (mode)
	{
		case 1:
			
		break;

		case 2:
			cerr << "\nTo quit enter logout authorization:";
		
			cin >> c;
			if(c=='q')
			{ cleanQuit("\nThankyou, goodbye!"); }
		break;
		default:
			return;
		break;
	}
}

void glutMenu(void)
{
	//int glut_menu[1];
	
	//glutCreateMenu(menu_select);
	
	//glutAddMenuEntry("item 1", 1);
	//glutAddMenuEntry("Quit", 2);
	
	//glutAttachMenuName(GLUT_RIGHT_BUTTON, "menu item");
}

void writeTextString(const SimpleVector& rasterPosition, char* nameString)
{
	glRasterPos2f(rasterPosition.v[vX], rasterPosition.v[vY]);
	
	int len = (int) strlen(nameString);
	
	for (int i = 0; i < len; i++)
	{	glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_10, nameString[i]);	}
}

